package rpc

import (
	"gitee.com/tietang/terrace-go/v2/lib/rpc/mo/entity"
	"gitee.com/tietang/terrace-go/v2/lib/rpc/models"
	"gitee.com/tietang/terrace-go/v2/lib/rpc/seri"
	log "github.com/sirupsen/logrus"
	"github.com/tietang/go-utils/errs"
	"reflect"
	"strconv"
	"strings"
)

var defaultDispatcher = newDispatcher()

func RegisterHandler(key string, handler Handler) {
	defaultDispatcher.Register(key, handler)
}

func AllHandlers() map[string]Handler {
	return defaultDispatcher.handlers
}

func Dispatch(mo *entity.MoEntity) (res *entity.ResEntity, err error) {
	res, err = defaultDispatcher.Send(mo)
	return
}

type Dispatcher struct {
	handlers map[string]Handler
}

func newDispatcher() *Dispatcher {
	return &Dispatcher{
		handlers: make(map[string]Handler, 16),
	}
}

func (d *Dispatcher) Send(mo *entity.MoEntity) (res *entity.ResEntity, err error) {
	res = entity.NewResEntity()
	res.Code = "200"
	res.Message = "成功"
	//log.Debug("数据：", mo.Type, " = ", string(mo.Data))
	serialization, found := seri.Get(mo.SerialType)
	if !found {
		res.Code = "500"
		res.Message = "不支持的序列化类型：" + strconv.Itoa(int(mo.SerialType))
		err = errs.NewError(res.Message, 500)
		return
	}
	typ := mo.Type
	typs := strings.Split(typ, ".")
	size := len(typs)
	typ = strings.Join(typs[size-2:size], ".")
	handler, found := d.handlers[typ]
	if !found {
		log.Error("找不到对应的handler：", typ)
		res.Code = "500"
		res.Message = "找不到对应的handler：" + typ
		return
	}
	mp, err := handler.Unmarshal(mo.Data, serialization) // d.getMessageType(handler)
	if err != nil {
		log.Error(err)
		res.Code = "500"
		res.Message = "失败:" + err.Error()
		return
	}
	msg := new(models.RpcMessage[any])
	msg.Message = mp
	msg.Type = typ
	handler.Handle(msg)
	return
}

func (d *Dispatcher) getMessageType(handler Handler) (typ reflect.Type) {
	typ1 := reflect.TypeOf(handler)
	m, found := typ1.MethodByName("Handle")
	if !found {
		return
	}
	atyp := m.Type.In(1)
	if atyp == nil {
		return
	}
	if atyp.Kind() == reflect.Ptr {
		atyp = atyp.Elem()
	}
	f, found := atyp.FieldByName("Message")
	if !found {
		return
	}
	return f.Type
}
func (h *Dispatcher) Register(key string, handler Handler) {
	_, found := h.handlers[key]
	if found {
		log.Info("已经存在的注册的sender:", handler)
		return
	}
	h.handlers[key] = handler
	log.Info("注册sender:", key, "=", reflect.ValueOf(handler).Type())
}
